package com.jinxin.platform.cdfaceacs.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jinxin.platform.base.common.pojo.InvokeCfg;
import com.jinxin.platform.base.common.pojo.JsonResult;
import com.jinxin.platform.base.common.support.BusinessDelegate;
import com.jinxin.platform.cdfaceacs.common.ResultEntity;
import com.jinxin.platform.cdfaceacs.mapper.JurenAcsControlDeviceInfoDao;
import com.jinxin.platform.cdfaceacs.mapper.JurenAcsControlSysParamMapper;
import com.jinxin.platform.cdfaceacs.mapper.JurenAcsControlUserInfoMapper;
import com.jinxin.platform.cdfaceacs.pojo.domains.*;
import com.jinxin.platform.cdfaceacs.service.AcsControlBlockInfoService;
import com.jinxin.platform.cdfaceacs.service.AcsControlDeviceInfoService;
import com.jinxin.platform.cdfaceacs.service.AcsControlDeviceSubscribeService;
import com.jinxin.platform.cdfaceacs.service.AcsControlRecordInfoService;
import com.jinxin.platform.cdfaceacs.utils.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;

import static com.jinxin.platform.cdfaceacs.utils.URLEncoder.encodeURIComponent;


/**
 * (AcsControlDeviceInfo)表服务实现类
 *
 * @author makejava
 * @since 2020-04-14 10:31:13
 */
@Service
@Slf4j
@Transactional
public class AcsControlDeviceInfoServiceImpl implements AcsControlDeviceInfoService {
    @Resource
    private JurenAcsControlDeviceInfoDao acsControlDeviceInfoDao;

    @Autowired
    private BusinessDelegate businessDelegate;

    @Autowired
    private AcsControlDeviceSubscribeService acsControlDeviceSubscribeService;

    @Resource
    private JurenAcsControlSysParamMapper sysParamMapper;

    @Resource
    private JurenAcsControlUserInfoMapper userInfoMapper;

    @Autowired
    private AcsControlRecordInfoService acsControlRecordInfoService;

    @Autowired
    private AcsControlBlockInfoService acsControlBlockInfoService;

    /**
     * 通过ID查询单条数据selAll
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public AcsControlDeviceInfo queryById(String id) {
        return this.acsControlDeviceInfoDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit 查询条数
     * @return 对象列表
     */
    @Override
    public List<AcsControlDeviceInfo> queryAllByLimit(int offset, int limit) {
        return this.acsControlDeviceInfoDao.queryAllByLimit(offset, limit);
    }

    @Override
    public PageInfo<AcsControlDeviceInfo> queryByLimitAndCondition(int offset, int limit, String type, String deviceName, String buildingLoc, String roomLoc) {
        PageHelper.startPage(offset,limit);
        List<AcsControlDeviceInfo> acsControlDeviceInfos = acsControlDeviceInfoDao.queryByLimitAndCondition(offset,limit,type,deviceName,buildingLoc,roomLoc);
        PageInfo<AcsControlDeviceInfo> pageInfo = new PageInfo<>(acsControlDeviceInfos);
        return pageInfo;
    }

    /**
     * 新增数据
     *
     * @param acsControlDeviceInfo 实例对象
     * @return 实例对象
     */
    @Override
    public AcsControlDeviceInfo insert(AcsControlDeviceInfo acsControlDeviceInfo) {
        this.acsControlDeviceInfoDao.insert(acsControlDeviceInfo);
        return acsControlDeviceInfo;
    }

    /**
     * 修改数据
     *
     * @param acsControlDeviceInfo 实例对象
     * @return 实例对象
     */
    @Override
    public AcsControlDeviceInfo update(AcsControlDeviceInfo acsControlDeviceInfo) {
        this.acsControlDeviceInfoDao.update(acsControlDeviceInfo);
        return this.queryById(acsControlDeviceInfo.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(String id) {
        return this.acsControlDeviceInfoDao.deleteById(id) > 0;
    }

    @Override
    public List<AcsControlDeviceInfo> selAll(){
        return acsControlDeviceInfoDao.queryAll(new AcsControlDeviceInfo());
    }

    @Override
    public AcsControlDeviceInfo selectByDeviceId(String deviceId) {
        return acsControlDeviceInfoDao.selectByDeviceId(deviceId);
    }

    @Override
    public AcsControlDeviceInfo selectByBuildingLoc(String buildingLoc) {
        return acsControlDeviceInfoDao.selectByBuildingLoc(buildingLoc);
    }

    @Override
    public Boolean controlDevice(AcsControlDeviceSubscribe acsControlDeviceSubscribe, String controlParams, String operation) {
        Map<String, String> serviceMap = getServiceInfo();
        InvokeCfg cfg = new InvokeCfg();
        cfg.setModuleKey("acsDevice");
        cfg.setClassName("acsDeviceService");
        cfg.setFunName("controlDevice");
        HashMap<String, String> resultMap = new HashMap<>();
        resultMap.put("controlParams", controlParams);
        resultMap.put("operation", operation);
        resultMap.put("serial_num", acsControlDeviceSubscribe.getDeviceMac());
        resultMap.put("productId", acsControlDeviceSubscribe.getProductCode());
        resultMap.put("account", acsControlDeviceSubscribe.getBccaAccount());
        resultMap.put("service_key", serviceMap.get("service_key"));
        resultMap.put("service_id", serviceMap.get("service_id"));
        cfg.setArgs(resultMap);
        JsonResult result = businessDelegate.invoke(cfg);
        log.info("controlDeviceResult--------"+result.getData().toString());
        return result.getSuccess();
    }

    public Map<String, String> getServiceInfo() {
        Map<String, String> resultMap = new HashMap<>();
        InvokeCfg cfg = new InvokeCfg();
        cfg.setModuleKey("acsDevice");
        cfg.setClassName("acsDeviceService");
        cfg.setFunName("getServiceInfo");
        cfg.setArgs(resultMap);
        JsonResult result = businessDelegate.invoke(cfg);
        if (result.getSuccess()) {
            JSONObject jsonObject = JSONObject.parseObject(result.getData().toString());
            resultMap.put("service_key", jsonObject.getString("service_key"));
            resultMap.put("service_id", jsonObject.getString("service_id"));
        }
        return resultMap;
    }

    @Override
    public boolean set(AcsControlDeviceInfo acsControlDeviceInfo, String mac) {
        String operation = "set";
        String controlParams;
        JSONObject jsonObject = new JSONObject();
        AcsControlSysParamDO sysParamDO = new AcsControlSysParamDO();
        jsonObject.put("p1", acsControlDeviceInfo.getUserInfo());
        jsonObject.put("p2", acsControlDeviceInfo.getCallNumber());
        sysParamDO.setParamKey("propertyNumber");
        jsonObject.put("p3", sysParamMapper.selParamByInfo(sysParamDO).get(0).getParamVal());
        controlParams = encodeURIComponent(jsonObject.toJSONString());
        return controlDevice(acsControlDeviceSubscribeService.queryById(mac), controlParams, operation);
    }

    @Override
    public boolean deleteFace(String userId, String mac){
        String controlParams;
        String operation = "Delete face information";
        AcsControlUserInfoDO acsControlUserInfoDO = userInfoMapper.selById(userId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("p1", acsControlUserInfoDO.getUserBlockName()+"-"+acsControlUserInfoDO.getUserRoomName()+"-"+acsControlUserInfoDO.getUserName());
        controlParams = encodeURIComponent(jsonObject.toJSONString());
        return controlDevice(acsControlDeviceSubscribeService.queryById(mac), controlParams, operation);
    }
    @Override
    public boolean deleteAllFace(String mac){
        String controlParams = "{}";
        String operation = "Delete all";
        return controlDevice(acsControlDeviceSubscribeService.queryById(mac), encodeURIComponent(controlParams), operation);
    }


    @Override
    public boolean register(AcsControlDeviceInfo acsControlDeviceInfo, List<AcsControlUserInfoDO> acsControlUserInfoDOS, String mac) {
        String operation;
        String controlParams;
        Boolean flag = true;
        operation = "Lower allocation";
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("p1", acsControlDeviceInfo.getCallNumber());
        AcsControlSysParamDO sysParamDO = new AcsControlSysParamDO();
        jsonObject.put("p2", acsControlDeviceInfo.getMonitoring());
        jsonObject.put("p3", acsControlDeviceInfo.getBuildingLoc().split("栋")[0]);
        sysParamDO.setParamKey("propertyNumber");
        jsonObject.put("p4", sysParamMapper.selParamByInfo(sysParamDO).get(0).getParamVal());
        controlParams = encodeURIComponent(jsonObject.toJSONString());
        controlDevice(acsControlDeviceSubscribeService.queryById(mac), controlParams, operation);
        if (acsControlUserInfoDOS.size()>0){
            operation = "Register face information";
            for (AcsControlUserInfoDO acsControlUserInfoDO :
                    acsControlUserInfoDOS) {
                jsonObject = new JSONObject();
                jsonObject.put("p1", acsControlUserInfoDO.getUserBlockName()+"-"+acsControlUserInfoDO.getUserRoomName()+"-"+acsControlUserInfoDO.getUserName());
                jsonObject.put("p2", acsControlUserInfoDO.getUserFaceInfo());
                controlParams = jsonObject.toJSONString();
                try {
                    if (!controlDevice(acsControlDeviceSubscribeService.queryById(mac), URLEncoder.encode(controlParams, "UTF-8"), operation)) {
                        flag = false;
                    }
                } catch (UnsupportedEncodingException e) {
                    log.error("错误",e);
                }
            }
        }

        return flag;
    }

    @Override
    public boolean getDevice() {
        InvokeCfg cfg1 = new InvokeCfg();
        cfg1.setModuleKey("acsDeviceInfo");
        cfg1.setClassName("acsDeviceInfoService");
        cfg1.setFunName("getBccaAccountList");
        JsonResult result1 = businessDelegate.invoke(cfg1);
        List<JSONObject> jsonObject1 = JSON.parseArray(result1.getData().toString(), JSONObject.class);
        for (JSONObject temp :
                jsonObject1) {
            String account = temp.getString("bcca_account");
            InvokeCfg cfg = new InvokeCfg();
            cfg.setModuleKey("acsDeviceInfo");
            cfg.setClassName("acsDeviceInfoService");
            cfg.setFunName("getAcsDeviceList");
            HashMap<String, String> resultMap = new HashMap<>();
            resultMap.put("account", account);
            resultMap.put("pageSize", "100000");
            resultMap.put("pageNo", "1");
            cfg.setArgs(resultMap);
            JsonResult result = businessDelegate.invoke(cfg);
            if (result.getSuccess()) {
                List<JSONObject> jsonObject = JSON.parseArray(result.getData().toString(), JSONObject.class);

                List<AcsControlDeviceSubscribe> tempList = new ArrayList<>();
                if (jsonObject.size() == 0){
                    log.info("无数据");
                    return false;
                }
                List<AcsControlDeviceSubscribe> acsControlDeviceSubscribes = acsControlDeviceSubscribeService.getAllDevice();
                for (JSONObject j :
                        jsonObject) {
                    AcsControlDeviceSubscribe acsControlDeviceSubscribe = new AcsControlDeviceSubscribe();
                    acsControlDeviceSubscribe.setCreateTime(LocalDateTime.now());
                    acsControlDeviceSubscribe.setDeviceMac(j.getString("device_mac"));
                    acsControlDeviceSubscribe.setProductCode(j.getString("product_code"));
                    acsControlDeviceSubscribe.setDeviceName(j.getString("device_name"));
                    acsControlDeviceSubscribe.setBccaAccount(account);
                    acsControlDeviceSubscribe.setIfUser("N");
                    tempList.add(acsControlDeviceSubscribe);

                    if (!containsMac(acsControlDeviceSubscribes,acsControlDeviceSubscribe)){
                        try {
                            acsControlDeviceSubscribeService.insert(acsControlDeviceSubscribe);
                        } catch (Exception e) {
                            log.error("数据库错误",e);
                        }
                    }
                    if (acsControlDeviceSubscribes.size()>tempList.size()){
                        List<String> macList = CollectionUtil.getDifferentMac(acsControlDeviceSubscribes,tempList);
                        for (String mac : macList) {
                            acsControlDeviceSubscribeService.deleteById(mac);
                        }
                    }
                }

            }
        }
        log.info("更新完毕");
        return result1.getSuccess();
    }

    @Override
    public ResultEntity saveDevice(AcsControlDeviceInfo acsControlDeviceInfo) {
        String mac = acsControlDeviceInfo.getDeviceId();
        try {
            switch (acsControlDeviceInfo.getType()) {
                case "单元门口机":
                case "门口闸机":
                    if (!StringUtils.isEmpty(acsControlDeviceInfo.getId())) {
                        AcsControlDeviceInfo acsControlDeviceInfo1 = queryById(acsControlDeviceInfo.getId());
                        if (acsControlDeviceInfo.getUserInfo() == null){
                            deleteAllFace(mac);
                        }
                        register(acsControlDeviceInfo, new ArrayList<>(), mac);
                        if (acsControlDeviceInfo1.getUserInfo()!=null&&acsControlDeviceInfo.getUserInfo()!=null&&!acsControlDeviceInfo1.getUserInfo().equals(acsControlDeviceInfo.getUserInfo())){
                            List<String> newUserInfo = new ArrayList(Arrays.asList(acsControlDeviceInfo.getUserInfo().split(",")));
                            List<String> oldUserInfo = new ArrayList(Arrays.asList(acsControlDeviceInfo1.getUserInfo().split(",")));
                            for (int i =0;i<newUserInfo.size();i++){
                                for (int j =0;j<oldUserInfo.size();j++){
                                    if (newUserInfo.get(i).equals(oldUserInfo.get(j))){
                                        newUserInfo.remove(i);
                                        oldUserInfo.remove(j);
                                        i--;
                                        j--;
                                        break;
                                    }
                                }
                            }
                            List<AcsControlUserInfoDO> newUserInfoDOS = new ArrayList<>();
                            for (String n:newUserInfo) {
                                newUserInfoDOS.add(userInfoMapper.selById(n));
                            }
                                register(acsControlDeviceInfo, newUserInfoDOS, mac);
                            for (String o:oldUserInfo) {
                                deleteFace(o, mac);
                            }
                        }
                    }else {
                        List<AcsControlUserInfoDO> acsControlUserInfoDOS = new ArrayList<>();
                        String[] userInfo = acsControlDeviceInfo.getUserInfo().split(",");
                        for (String s :
                                userInfo) {
                            acsControlUserInfoDOS.add(userInfoMapper.selById(s));
                        }
                        register(acsControlDeviceInfo, acsControlUserInfoDOS, mac);
                    }
                    if (acsControlDeviceInfo.getType().equals("单元门口机")){
                        AcsControlBlockInfoDO acsControlBlockInfoDO = new AcsControlBlockInfoDO();
                        acsControlBlockInfoDO.setBlockName(acsControlDeviceInfo.getBuildingLoc());
                        List<AcsControlBlockInfoDO> acsControlBlockInfoDOS = acsControlBlockInfoService.selDOByInfo(acsControlBlockInfoDO);
                        acsControlBlockInfoDOS.get(0).setState("1");
                        acsControlBlockInfoService.updateDO(acsControlBlockInfoDOS.get(0));
                    }
                    break;
                case "业主室内机":
                    set(acsControlDeviceInfo, mac);
                    break;
                case "物业室内机":
                    AcsControlDeviceInfo acsControlDeviceInfo1 = new AcsControlDeviceInfo();
                    acsControlDeviceInfo1.setType("物业室内机");
                    List<AcsControlDeviceInfo> acsControlDeviceInfos = acsControlDeviceInfoDao.queryAll(acsControlDeviceInfo1);
                    for (AcsControlDeviceInfo a :
                            acsControlDeviceInfos) {
                        if (a.getCallNumber().equals(acsControlDeviceInfo.getCallNumber())) {
                            return new ResultEntity("NO", "不能添加相同的呼叫号码!");
                        }
                    }
                    AcsControlSysParamDO acsControlSysParamDO = new AcsControlSysParamDO();
                    acsControlSysParamDO.setParamKey("propertyNumber");
                    acsControlSysParamDO = sysParamMapper.selParamByInfo(acsControlSysParamDO).get(0);
                    acsControlSysParamDO.setParamVal(acsControlDeviceInfo.getCallNumber());
                    sysParamMapper.updateByPrimaryKey(acsControlSysParamDO);
                    set(acsControlDeviceInfo, mac);
                    break;
            }
        } catch (Exception e) {
            log.error("失败",e);
            return new ResultEntity("NO", "失败!");
        }

        if (StringUtils.isEmpty(acsControlDeviceInfo.getId())) {
            acsControlDeviceInfo.setCreateTime(LocalDateTime.now());
            AcsControlDeviceSubscribe acsControlDeviceSubscribe = acsControlDeviceSubscribeService.queryById(acsControlDeviceInfo.getDeviceId());
            acsControlDeviceSubscribe.setIfUser("Y");
            acsControlDeviceSubscribeService.update(acsControlDeviceSubscribe);
            if (acsControlDeviceInfo.getType().equals("单元门口机")||acsControlDeviceInfo.getType().equals("门口闸机")){
                acsControlDeviceInfo.setMonitoring(null);
            }else {
                acsControlDeviceInfo.setUserInfo(null);
            }
            insert(acsControlDeviceInfo);
        } else {
            update(acsControlDeviceInfo);
        }
        return new ResultEntity("OK", "成功!");
    }

    @Override
    public void sendMessage(String mac,String msg){
        String operation = "Send Message";
        JSONObject params = new JSONObject();
        params.put("p1",msg);
        String controlParams = encodeURIComponent(params.toJSONString());
        AcsControlDeviceSubscribe acsControlDeviceSubscribe = acsControlDeviceSubscribeService.queryById(mac);
        controlDevice(acsControlDeviceSubscribe, controlParams, operation);
    }

    @Override
    public String openDoor(String mac) {
        String operation = "Open door";
        String controlParams = "{}";
        controlParams = encodeURIComponent(controlParams);
        AcsControlDeviceSubscribe acsControlDeviceSubscribe = acsControlDeviceSubscribeService.queryById(mac);
        if (acsControlDeviceSubscribe != null) {
            AcsControlDeviceInfo acsControlDeviceInfo = selectByDeviceId(mac);
            AcsControlDeviceInfo acsControlDeviceInfo1 = selectByBuildingLoc(acsControlDeviceInfo.getBuildingLoc());
            AcsControlDeviceSubscribe door = acsControlDeviceSubscribeService.queryById(acsControlDeviceInfo1.getDeviceId());
            if (controlDevice(door, controlParams, operation)){
                return "开门成功";
            }
            return "开门失败";
        }
        return "未注册设备!";
    }

    @Override
    public String compare(String mac, String password, String type) {
        AcsControlRecordInfo acsControlRecordInfo = acsControlRecordInfoService.queryByInfo(password);
        if (!(acsControlRecordInfo == null)) {
            // 校验是否过期
            if(acsControlRecordInfo.getListenedTime().isBefore(LocalDateTime.now()) ){
                return  "验证信息已过期";
            }
            // 更新邀请码状态为2 已使用
            if(null == acsControlRecordInfo.getState() || acsControlRecordInfo.getState().equals("1") ){
                acsControlRecordInfo.setState("2");
                acsControlRecordInfoService.update(acsControlRecordInfo);
            }
            //发送开门指令
            String operation = "Open door";
            String controlParams = "{}";
            AcsControlDeviceSubscribe acsControlDeviceSubscribe = acsControlDeviceSubscribeService.queryById(mac);
            if (controlDevice(acsControlDeviceSubscribe,
                    encodeURIComponent(controlParams), operation)){
                return "开门成功";
            }
            return  "开门失败";
        }
        if (type.equals("password")){
            return "输入密码错误";
        }
        return "无效二维码";
    }

    @Override
    public List<AcsControlDeviceInfo> selAllByParam(AcsControlDeviceInfo info) {
        return acsControlDeviceInfoDao.queryAll(info);
    }

    public boolean containsMac(List<AcsControlDeviceSubscribe> acsControlDeviceSubscribes,AcsControlDeviceSubscribe acsControlDeviceSubscribe){
        for (AcsControlDeviceSubscribe temp : acsControlDeviceSubscribes) {
            if (temp.getDeviceMac().equals(acsControlDeviceSubscribe.getDeviceMac())) {
                return true;
            }
        }
        return false;
    }
}